/*  SSSharedNewEBPanelController.m
 *  MESLib
 * 
 * Copyright 2003-2009 Starline Software Ltd
 * 
 * This file is part of MESLib.
 * 
 * MESLib is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * MESLib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with MESLib. If not, see <http://www.gnu.org/licenses/>.
 */
//  Created by Tobias Haughton on Fri Jan 24 2003.
//

#import "SSSharedNewEBPanelController.h"
#import "SSCatalystDocument.h"

@implementation SSSharedNewEBPanelController

+ (id)sharedNewEBController {
   static SSSharedNewEBPanelController *sharedNewEBController = nil;

   if(!sharedNewEBController) {
      sharedNewEBController = [[SSSharedNewEBPanelController allocWithZone:[self zone]] init];
   }
   return sharedNewEBController;
}

- (id)init {
   self = [super initWithWindowNibName:@"NewEBPanel"];
   if (self) {
      [self setWindowFrameAutosaveName:@"NewEBPanel"];
      [[NSNotificationCenter defaultCenter] addObserver:self
             selector:@selector(reloadComboBoxes)
                 name:@"SSDataSourceDictionaryChanged"
               object:nil];
   }
   return self;
}

- (void)awakeFromNib
{
   SSChartDate *today = [SSChartDate calendarDate];
   NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] initWithDateFormat:[NSString stringWithFormat:@"%@:%@:%@",
      @"%Y", @"%m", @"%d"] allowNaturalLanguage:NO] autorelease];
   [beginDateField setFormatter:dateFormatter];
   [endDateField setFormatter:dateFormatter]; //set the formatter for the 2 date fields
   [beginDateField setObjectValue:today];
   [endDateField setObjectValue:today];
   
   NSDateFormatter *timeFormatter = [[[NSDateFormatter alloc] initWithDateFormat:[NSString stringWithFormat:@"%@:%@:%@:%@",
      @"%H", @"%M", @"%S", @"%F"] allowNaturalLanguage:NO] autorelease];
   [beginTimeField setFormatter:timeFormatter];
   [endTimeField setFormatter:timeFormatter];
   [beginTimeField setObjectValue:today];
   [endTimeField setObjectValue:today];

   SSSourceFormatter *sourceFormatter = [[[SSSourceFormatter alloc] init] autorelease];
   [sourceCombobox setFormatter:sourceFormatter];

   SSEBDurationFormatter *durationFormatter = [[[SSEBDurationFormatter alloc] init] autorelease];
   [durationField setFormatter:durationFormatter];
   [self updateDurationFieldBasedOnDates];
   
   //create SSColoredButtonCells for the label matrix
   SSColoredButtonCell *whiteButtonCell = [[SSColoredButtonCell alloc] initTextCell:[NSString string] backgroundColor:SSWhiteColor];
   [whiteButtonCell setTag:SSWhiteLabelType];
   [whiteButtonCell setButtonType:NSPushOnPushOffButton];
   [whiteButtonCell setBezelStyle:NSShadowlessSquareBezelStyle];
   [labelMatrix putCell:whiteButtonCell atRow:0 column:0];

   SSColoredButtonCell *yellowButtonCell = [[SSColoredButtonCell alloc] initTextCell:[NSString string] backgroundColor:SSYellowColor];
   [yellowButtonCell setTag:SSYellowLabelType];
   [yellowButtonCell setButtonType:NSPushOnPushOffButton];
   [yellowButtonCell setBezelStyle:NSShadowlessSquareBezelStyle];
   [labelMatrix putCell:yellowButtonCell atRow:0 column:1];

   SSColoredButtonCell *greenButtonCell = [[SSColoredButtonCell alloc] initTextCell:[NSString string] backgroundColor:SSGreenColor];
   [greenButtonCell setTag:SSGreenLabelType];
   [greenButtonCell setButtonType:NSPushOnPushOffButton];
   [greenButtonCell setBezelStyle:NSShadowlessSquareBezelStyle];
   [labelMatrix putCell:greenButtonCell atRow:0 column:2];

   SSColoredButtonCell *lightBlueButtonCell = [[SSColoredButtonCell alloc] initTextCell:[NSString string] backgroundColor:SSLightBlueColor];
   [lightBlueButtonCell setTag:SSLightBlueLabelType];
   [lightBlueButtonCell setButtonType:NSPushOnPushOffButton];
   [lightBlueButtonCell setBezelStyle:NSShadowlessSquareBezelStyle];
   [labelMatrix putCell:lightBlueButtonCell atRow:0 column:3];

   SSColoredButtonCell *blueButtonCell = [[SSColoredButtonCell alloc] initTextCell:[NSString string] backgroundColor:SSBlueColor];
   [blueButtonCell setTag:SSBlueLabelType];
   [blueButtonCell setButtonType:NSPushOnPushOffButton];
   [blueButtonCell setBezelStyle:NSShadowlessSquareBezelStyle];
   [labelMatrix putCell:blueButtonCell atRow:0 column:4];

   SSColoredButtonCell *purpleButtonCell = [[SSColoredButtonCell alloc] initTextCell:[NSString string] backgroundColor:SSPurpleColor];
   [purpleButtonCell setTag:SSPurpleLabelType];
   [purpleButtonCell setButtonType:NSPushOnPushOffButton];
   [purpleButtonCell setBezelStyle:NSShadowlessSquareBezelStyle];
   [labelMatrix putCell:purpleButtonCell atRow:0 column:5];

   SSColoredButtonCell *orangeButtonCell = [[SSColoredButtonCell alloc] initTextCell:[NSString string] backgroundColor:SSOrangeColor];
   [orangeButtonCell setTag:SSOrangeLabelType];
   [orangeButtonCell setButtonType:NSPushOnPushOffButton];
   [orangeButtonCell setBezelStyle:NSShadowlessSquareBezelStyle];
   [labelMatrix putCell:orangeButtonCell atRow:0 column:6];

   SSColoredButtonCell *redButtonCell = [[SSColoredButtonCell alloc] initTextCell:[NSString string] backgroundColor:SSRedColor];
   [redButtonCell setTag:SSRedLabelType];
   [redButtonCell setButtonType:NSPushOnPushOffButton];
   [redButtonCell setBezelStyle:NSShadowlessSquareBezelStyle];
   [labelMatrix putCell:redButtonCell atRow:0 column:7];

   [labelMatrix selectCellWithTag:SSWhiteLabelType];

   //add all of our fields to be watched for text entry
   [[SSTextEntryValidationMK2 sharedTextEntryValidation] addWatchedControl:sourceCombobox];
   [[SSTextEntryValidationMK2 sharedTextEntryValidation] addWatchedControl:actorCombobox];
   [[SSTextEntryValidationMK2 sharedTextEntryValidation] addWatchedControl:actionCombobox];
   [[SSTextEntryValidationMK2 sharedTextEntryValidation] addWatchedControl:locationCombobox];
   [[SSTextEntryValidationMK2 sharedTextEntryValidation] addWatchedControl:objectCombobox];
}

- (IBAction)showWindow:(id)sender
{
   [super showWindow:sender];

   [sourceCombobox reloadData];
   [actorCombobox reloadData];
   [actionCombobox reloadData];
   [locationCombobox reloadData];
   [objectCombobox reloadData];
   [remarkCombobox reloadData];
}

- (IBAction)addEventBlock:(id)sender
{
   BOOL addEvent = YES;
   
   //update the duration
   [self updateDuration:self];
   
   SSEventObject *event = [[[SSEventObject alloc] initWithActor:[actorCombobox stringValue]
                                                         action:[actionCombobox stringValue]
                                                         object:[objectCombobox stringValue]
                                                       location:[locationCombobox stringValue]
                                                      beginTime:[self beginTimeFromFields]
                                                        endTime:[self endTimeFromFields]
                                                         source:[sourceCombobox objectValue]
                                                        remark:[remarkCombobox stringValue]
                                                        address:[[[NSDocumentController sharedDocumentController] currentDocument] addressForNewEvent]
                                                          label:[NSNumber numberWithInt:[[labelMatrix selectedCell] tag]]] autorelease];

   if([[NSUserDefaults standardUserDefaults] boolForKey:SSDisplayDupeWarningKey]) {
      //user wants to recieve dupe warnings
      if([[[NSDocumentController sharedDocumentController] currentDocument] eventExistsWithActorAndTime:event]) {
         //there is an event with this actor and time so alert the user and see what they want to do
         int choice = NSRunAlertPanel(NSLocalizedString(@"Error", nil), [NSString stringWithFormat:@"%@", NSLocalizedString(@"ExistingEvent", nil)], @"Add Event", @"Change Details", nil);
         if(choice != NSAlertDefaultReturn) {
            //user doesn't want to add the event
            addEvent = NO;
         }
      }
   }

   if([[event beginTime] compare:[event endTime]] == NSOrderedDescending) {
      int choice = NSRunAlertPanel(NSLocalizedString(@"Alert", nil), NSLocalizedString(@"NewEBEndDateIsBeforeBegin", nil), @"Change Details", @"Add Event", nil);
      if(choice == NSAlertDefaultReturn) {
         //user doesn't want to add the event
         addEvent = NO;
      }
   }
   
   if(addEvent) {
      [[[NSDocumentController sharedDocumentController] currentDocument] addNewEventBlock:event];
      [self clearUncheckedFields];
   }
}

- (IBAction)updateDuration:(id)sender
{
   if([beginDateField objectValue] || [beginTimeField objectValue]) {
      //increment the end date/time
      NSCalendarDate *incrementedDate = [[[NSCalendarDate alloc] initWithTimeInterval:[[durationField objectValue] doubleValue] sinceDate:[self beginTimeFromFields]] autorelease];
      [endDateField setObjectValue:incrementedDate];
      [endTimeField setObjectValue:incrementedDate];
   }
}

- (void)updateDurationFieldBasedOnDates 
{
   //set the duration field value based on our 2 dates
   [durationField setObjectValue:[NSNumber numberWithDouble:[[self endTimeFromFields] timeIntervalSinceDate:[self beginTimeFromFields]]]];   
}

- (IBAction)clearFields:(id)sender
{
   [actorCombobox setStringValue:[NSString string]];

   [actionCombobox setStringValue:[NSString string]];

   [objectCombobox setStringValue:[NSString string]];

   [locationCombobox setStringValue:[NSString string]];

   [remarkCombobox setStringValue:[NSString string]];

   [sourceCombobox setObjectValue:[NSArray array]];
   
  // [sourceCombobox setObjectValue:[NSNumber numberWithDouble:0]];

   [labelMatrix selectCellWithTag:SSWhiteLabelType];
   
   [durationField setObjectValue:[NSNumber numberWithDouble:0.0]];
   [self updateDuration:self];
}

- (void)clearUncheckedFields
{
   //clear fields which don't have a selected check box
   
   if(![actorCheckBox state]) {
      [actorCombobox setStringValue:[NSString string]];
   }

   if(![actionCheckBox state]) {
      [actionCombobox setStringValue:[NSString string]];
   }

   if(![objectCheckBox state]) {
      [objectCombobox setStringValue:[NSString string]];
   }

   if(![locationCheckBox state]) {
      [locationCombobox setStringValue:[NSString string]];
   }

   if(![remarkCheckBox state]) {
      [remarkCombobox setStringValue:[NSString string]];
   }

   if(![sourceCheckBox state]) {
      [sourceCombobox setObjectValue:[NSArray array]];
   }

   if(![labelCheckBox state]) {
      [labelMatrix selectCellWithTag:SSWhiteLabelType];
   }
}

- (void)reloadComboBoxes
{
   [sourceCombobox reloadData];
   [actorCombobox reloadData];
   [actionCombobox reloadData];
   [locationCombobox reloadData];
   [objectCombobox reloadData];
   [remarkCombobox reloadData];
}

//***********************************
- (SSChartDate *)beginTimeFromFields
{
   BOOL timeIsEstimated;
   SSChartDate *finalDate;
   NSCalendarDate *dateObject = [beginDateField objectValue];
   NSCalendarDate *timeObject = [beginTimeField objectValue];

   if([beginTimeCheckBox state]) {
      timeIsEstimated = NO;
   } else {
      timeIsEstimated = YES;
   }
   
   if(dateObject && timeObject) {
      //ther is a begin date and time so joing them into the same date
      finalDate = [[[SSChartDate alloc] initWithString:[NSString stringWithFormat:@"%@/%@/%@/%@/%@/%@/%@", [dateObject descriptionWithCalendarFormat:@"%Y"],
         [dateObject descriptionWithCalendarFormat:@"%m"], [dateObject descriptionWithCalendarFormat:@"%d"], [timeObject descriptionWithCalendarFormat:@"%H"],
         [timeObject descriptionWithCalendarFormat:@"%M"], [timeObject descriptionWithCalendarFormat:@"%S"], [timeObject descriptionWithCalendarFormat:@"%F"]]
                                    calendarFormat:@"%Y/%m/%d/%H/%M/%S/%F" isEstimated:timeIsEstimated] autorelease];
   } else {
      if(dateObject) {
         //there is a begin date but no time
          finalDate = [SSChartDate chartDateWithCalendarDate:dateObject isEstimated:timeIsEstimated];
      } else {
         if(timeObject) {
            //there is a time but no date
            finalDate = [SSChartDate chartDateWithCalendarDate:timeObject isEstimated:timeIsEstimated];
         } else {
            //there is no time or date
            finalDate = [SSChartDate chartDateWithCalendarDate:[NSCalendarDate calendarDate] isEstimated:timeIsEstimated];
         }
      }
   }

   return finalDate;
}

- (SSChartDate *)endTimeFromFields
{
   BOOL timeIsEstimated;
   SSChartDate *finalDate;
   NSCalendarDate *dateObject = [endDateField objectValue];
   NSCalendarDate *timeObject = [endTimeField objectValue];

   if([endTimeCheckBox state]) {
      timeIsEstimated = NO;
   } else {
      timeIsEstimated = YES;
   }

   if(dateObject && timeObject) {
      //ther is a end date and time so joing them into the same date
      finalDate = [[[SSChartDate alloc] initWithString:[NSString stringWithFormat:@"%@/%@/%@/%@/%@/%@/%@", [dateObject descriptionWithCalendarFormat:@"%Y"],
         [dateObject descriptionWithCalendarFormat:@"%m"], [dateObject descriptionWithCalendarFormat:@"%d"], [timeObject descriptionWithCalendarFormat:@"%H"],
         [timeObject descriptionWithCalendarFormat:@"%M"], [timeObject descriptionWithCalendarFormat:@"%S"], [timeObject descriptionWithCalendarFormat:@"%F"]]
                                    calendarFormat:@"%Y/%m/%d/%H/%M/%S/%F" isEstimated:timeIsEstimated] autorelease];
   } else {
      if(dateObject) {
         //there is a end date but no time
         finalDate = [SSChartDate chartDateWithCalendarDate:dateObject isEstimated:timeIsEstimated];
      } else {
         if(timeObject) {
            //there is a time but no date
            finalDate = [SSChartDate chartDateWithCalendarDate:timeObject isEstimated:timeIsEstimated];
         } else {
            //there is no time or date
            finalDate = [SSChartDate chartDateWithCalendarDate:[NSCalendarDate calendarDate] isEstimated:timeIsEstimated];
         }
      }
   }

   return finalDate;
}

//***********************************
- (void)controlTextDidEndEditing:(NSNotification *)note
{
   if([[note object] isEqualTo:beginDateField] || [[note object] isEqualTo:beginTimeField] ||
      [[note object] isEqualTo:endDateField] || [[note object] isEqualTo:endTimeField]) {
      //up date the duration to represent the change
      [self updateDurationFieldBasedOnDates];
   }
}


- (BOOL)control:(NSControl *)control didFailToFormatString:(NSString *)string 
        errorDescription:(NSString *)error
{
   if([control isEqualTo:beginTimeField] || [control isEqualTo:endTimeField]) {
      //break the string into it's time segments
      NSArray *timeArray = [string componentsSeparatedByString:@":"];
      NSString *timeString = [NSString string];
      int i = 0;

      while(i < [timeArray count] && i < 4) {
      	//include the < 4 incase the user has entered too many values
         timeString = [timeString stringByAppendingString:[timeArray objectAtIndex:i]]; //add the time value to the string

         if(i < 3) {
            //add the seperator
            timeString = [timeString stringByAppendingString:@":"];
         }

         i++;
      }

      while(i < 4) {
         //we have used all of the user entered values so pad with 0
         timeString = [timeString stringByAppendingString:@"0"];

         if(i < 3) {
            //add the seperator
            timeString = [timeString stringByAppendingString:@":"];
         }

         i++;
      }

      SSChartDate *cd = [[[SSChartDate alloc] initWithString:timeString calendarFormat:@"%H:%M:%S:%F"] autorelease];

      if(cd) {
         //the new date is valid so set the fields value to that
         [control setObjectValue:cd];
      } else {
         //the user entered un usable info so set the date to now
         [control setObjectValue:[SSChartDate calendarDate]];
      }      
   } else if([control isEqualTo:beginDateField] || [control isEqualTo:endDateField]) {
      //it's a date
      [control setObjectValue:[SSChartDate calendarDate]];
   }
   
   
   return NO;
}

//***********************************combobox datasource
- (int)numberOfItemsInComboBox:(NSComboBox *)aComboBox
{
   switch([aComboBox tag]) {
      case 101:
         return [[[NSDocumentController sharedDocumentController] currentDocument] numberOfUniqueSources];
         break;
      case 102:
         return [[[NSDocumentController sharedDocumentController] currentDocument] numberOfUniqueActors];
         break;
      case 103:
         return [[[NSDocumentController sharedDocumentController] currentDocument] numberOfUniqueActions];
         break;
      case 104:
         return [[[NSDocumentController sharedDocumentController] currentDocument] numberOfUniqueLocations];
         break;
      case 105:
         return [[[NSDocumentController sharedDocumentController] currentDocument] numberOfUniqueObjects];
         break;
      case 106:
         return [[[NSDocumentController sharedDocumentController] currentDocument] numberOfUniqueRemarks];
         break;
      default:
         return 0;
         break;
   }
}

- (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(int)index
{
   id record = nil;
   
   switch([aComboBox tag]) {
      case 101:
         record = [[[NSDocumentController sharedDocumentController] currentDocument] alphabeticDataSourceDictionaryArrayWithKey:@"source" objectAtIndex:index];
         break;
      case 102:
         record = [[[NSDocumentController sharedDocumentController] currentDocument] alphabeticDataSourceDictionaryArrayWithKey:@"actor" objectAtIndex:index];
         break;
      case 103:
         record = [[[NSDocumentController sharedDocumentController] currentDocument] alphabeticDataSourceDictionaryArrayWithKey:@"action" objectAtIndex:index];
         break;
      case 104:
         record = [[[NSDocumentController sharedDocumentController] currentDocument] alphabeticDataSourceDictionaryArrayWithKey:@"location" objectAtIndex:index];
         break;
      case 105:
         record = [[[NSDocumentController sharedDocumentController] currentDocument] alphabeticDataSourceDictionaryArrayWithKey:@"object" objectAtIndex:index];
         break;
      case 106:
         record = [[[NSDocumentController sharedDocumentController] currentDocument] alphabeticDataSourceDictionaryArrayWithKey:@"remark" objectAtIndex:index];
         break;
      default:
         break;
   }

   return record;
}

//***********************************
- (BOOL)receiveClickedDateInfo
{
   //test to see if one of our date fields is being editied
   if([beginDateField currentEditor] || [beginTimeField currentEditor] ||
      [endDateField currentEditor] || [endTimeField currentEditor]) {
      return YES;
   }

   return NO;
}

- (void)userClickedDate:(SSChartDate *)date
{
   if([beginDateField currentEditor] || [beginTimeField currentEditor]) {
      // begin time is being edited insert date
      [beginDateField setObjectValue:date];
      [beginTimeField setObjectValue:date];

      //end editing so that the new value is set
      if([beginDateField currentEditor]) {
         [[beginDateField cell] endEditing:[beginDateField currentEditor]];
      } else {
         [[beginTimeField cell] endEditing:[beginTimeField currentEditor]];
      }
   } else if([endDateField currentEditor] || [endTimeField currentEditor]) {
      //end time is being edited
      [endDateField setObjectValue:date];
      [endTimeField setObjectValue:date];

      //end editing so that the new value is set
      if([endDateField currentEditor]) {
         [[endDateField cell] endEditing:[endDateField currentEditor]];
      } else {
         [[endTimeField cell] endEditing:[endTimeField currentEditor]];
      }
   }
}

//***********************************
- (void)dealloc
{
   [[NSNotificationCenter defaultCenter] removeObserver:self];
   [super dealloc];
}


@end
